/**
 * Copyright (c) 2019 Coder League
 * All rights reserved.
 *
 * File：AuthorityInterceptor.java
 * History:
 *         2019年5月15日: Initially created, Chrise.
 */
package club.coderleague.ilsp.interceptor;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;

import club.coderleague.ilsp.common.annotation.PreAuthorize;
import club.coderleague.ilsp.common.domain.beans.UserSession;
import club.coderleague.ilsp.util.CommonUtil;

/**
 * 授权拦截器。
 * @author Chrise
 */
public class AuthorityInterceptor implements AsyncHandlerInterceptor {
	/**
	 * @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if (!(handler instanceof HandlerMethod)) return true;
		
		HttpSession session = request.getSession(false);
		UserSession user = (session == null) ? null : (UserSession)session.getAttribute(UserSession.SESSION_KEY);
		if (user != null) {
			List<String> authorities = user.getAuthorities();
			
			// 获取授权策略
			PreAuthorize auth = ((HandlerMethod)handler).getMethodAnnotation(PreAuthorize.class);
			String[] policies = (auth == null) ? null : auth.value();
			
			if (policies != null) {
				for (String policy : policies) {
					while (true) {
						if (CommonUtil.isEmpty(policy)) break;	// 搜索完毕
						
						if ("*".equals(policy)) return true;	// 通配符授权时允许访问
						
						// 继承父级授权
						int index = policy.lastIndexOf(".");
						if (index != -1 && policy.endsWith("*")) {
							policy = policy.substring(0, index);
							continue;
						}
						
						// 验证授权
						boolean accessable = false;
						for (String authority : authorities) {
							if (policy.equals(authority)) {
								accessable = true;
								break;
							}
						}
						if (accessable) return true;			// 验证通过时允许访问
						
						break;	// 验证失败终止搜索
					}
				}
			}
		}
		
		// 默认禁止访问
		response.sendError(HttpServletResponse.SC_FORBIDDEN);
		return false;
	}
}
